/*
 * This file is part of the Android Dimensions Editor Project: http://code.google.com/p/android-dimension-editor/
 *  
 * Copyright (c) 2013 Rick Falck
 *  
 * This code is licensed under the terms of the Apache License Version 2.0.
 * You may use this code according to the license.
 *
 * The terms of the license can be found in the root directory of this project's repository as well as at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under these Licenses is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See each License for the specific language governing permissions and
 * limitations under that License.
 */

package model;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.xml.stream.XMLStreamException;

import model.ReturnInfo.ERROR_TYPE;
import application.DimensFile_XML_RW;

/**
 * <b>public class DimensFile</b>
 * <p>
 * One Dimens.xml file.
 * 
 * @author Rick Falck
 * 
 */
public class DimensFile {
	public static final String DEFAULT_VALUE = "0dp";
	public static final String COMMENT_VALUE = "-";
	
	public static DimensFile createNewFile(String folderName, File file, List<ItemName> itemNameSet) {
		DimensFile newFile = new DimensFile(folderName, file);

		for (ItemName name : itemNameSet) {
			ItemName n = new ItemName(name.getText());
			ItemValue v;
			if (name.isComment()) {
				v = new ItemValue(COMMENT_VALUE, false);
			} else {
				v = new ItemValue(DEFAULT_VALUE, true);
			}
			
			n.setMyValue(v);
			newFile.nNameValueMap.add(n);
		}
		return newFile;
	}
	
	private final String mFolderName; // Folder name, like "values-v11"
	private final File mFilePath; // Full path to the dimens.xml file in this
									// folder
	private ArrayList<ItemName> nNameValueMap = new ArrayList<>();

	private boolean mFileSaved;
	private boolean mNewFile;

	public DimensFile(String folderName, File filePath) {
		mFolderName = folderName;
		mFilePath = filePath;
		mFileSaved = false;
		mNewFile = true;
	}

	public List<ItemName> getItemNames() {
		return nNameValueMap;
	}

	public String getFolderName() {
		return mFolderName;
	}

	public ItemValue getValue(ItemName name) {
		for (ItemName n : nNameValueMap) {
			if (n.equals(name)) {
				return n.getMyValue();
			}
		}
		return null;
	}

	public void addNewItem(ItemName currentItem, String newItemName, boolean insertAbove) {
		ItemName n = new ItemName(newItemName);
		ItemValue v = new ItemValue(DEFAULT_VALUE, true);
		n.setMyValue(v);
		int pos = nNameValueMap.indexOf(currentItem);
		if (pos == -1) {
			return;
		}
		if (insertAbove) {
			nNameValueMap.add(pos, n);
		} else {
			if (pos == nNameValueMap.size() - 1) {
				nNameValueMap.add(n);
			} else {
				nNameValueMap.add(pos+1, n);
			}
		}
		mFileSaved = false;
	}
	
	public void addNewComment(ItemName currentItem, String comment) {
		ItemComment n = new ItemComment(comment);
		ItemValue v = new ItemValue(COMMENT_VALUE, false);
		n.setMyValue(v);
		int pos = nNameValueMap.indexOf(currentItem);
		if (pos == -1) {
			return;
		}
		
		nNameValueMap.add(pos, n);
		mFileSaved = false;
	}

	public void delete() {
		if (!mNewFile) {
			mFilePath.delete();
			File path = new File(mFilePath.getParent());
			
			String[] otherFiles = path.list();

			if (otherFiles != null && otherFiles.length == 0) {
				path.delete();
			}
		}
	}

	public boolean isFileSaved() {
		return mFileSaved;
	}

	public ReturnInfo readFile() {
		ReturnInfo ret = new ReturnInfo(true);
		mFileSaved = true;
		mNewFile = false;
		try {
			nNameValueMap = DimensFile_XML_RW.readFile(mFilePath);
		} catch (FileNotFoundException | XMLStreamException e) {
			//e.printStackTrace();
			ret.setErrorMessage(e.getMessage());
			ret.setErrorType(ERROR_TYPE.XML_READ);
			ret.setSuccess(false);
		}
		return ret;
	}

	public ReturnInfo editValues() {
		ReturnInfo retInfo = new ReturnInfo(true);

		for (ItemName iName : nNameValueMap) {
			if (!iName.isComment() && !iName.getMyValue().editValue()) {
				retInfo.setSuccess(false);
				retInfo.setErrorType(ERROR_TYPE.FIELD_FORMAT);
				retInfo.setErrorMessage("Invalid value found in file: " + mFolderName
								+ System.lineSeparator() + "value: " + iName.getMyValue().getText());
				return retInfo;
			}
		}

		return retInfo;
	}

	public ReturnInfo save() {
		ReturnInfo retInfo = new ReturnInfo(true);

		for (ItemName iName : nNameValueMap) {
			if (iName.getMyValue().isNameChanged()) {
				mFileSaved = false;
				iName.getMyValue().setToCurrentName();
			}
		}

		if (!mFileSaved) {
			mFileSaved = true;
			mNewFile = false;

			try {
				File path = new File(mFilePath.getParent());
				if (!path.exists()) {
					path.mkdir();
				}
				DimensFile_XML_RW.writeFile(mFilePath, nNameValueMap);

			} catch (XMLStreamException e) {
				e.printStackTrace();
				retInfo.setSuccess(false);
				retInfo.setErrorMessage(e.getMessage());
				retInfo.setErrorType(ERROR_TYPE.XML_WRITE);
			} catch (IOException e) {
				e.printStackTrace();
				retInfo.setSuccess(false);
				retInfo.setErrorMessage(e.getMessage());
				retInfo.setErrorType(ERROR_TYPE.FILE_IO);
			} catch (Exception e) {
				e.printStackTrace();
				retInfo.setSuccess(false);
				retInfo.setErrorMessage(e.getMessage());
				retInfo.setErrorType(ERROR_TYPE.OTHER);
			}
		}

		return retInfo;
	}

	public void deleteItemName(ItemName itemName) {
		nNameValueMap.remove(itemName);
		mFileSaved = false;
	}

	public void changeItemName(String oldName, String newName) {
		for (ItemTextField iName : nNameValueMap) {
			if (iName.toString().equals(oldName)) {
				iName.setText(newName);
				iName.setToCurrentName();
				break;
			}
		}
		mFileSaved = false;
	}

	public boolean isNewFile() {
		return mNewFile;
	}

	public void setNewFile(boolean newFile) {
		mNewFile = newFile;
	}

	public void addIfMissing(ItemName name) {
		if (!nNameValueMap.contains(name)) {
			ItemName newName;
			ItemValue newValue;
			if (!name.isComment()) {
				newName = new ItemComment(name.getOriginalString());
				newValue = new ItemValue(DEFAULT_VALUE, true);
				
			} else {
				newName = new ItemName(name.getOriginalString());
				newValue = new ItemValue(COMMENT_VALUE, false);
			}
			newName.setMyValue(newValue);
			nNameValueMap.add(newName);
		}		
	}

	public void sort() {
		Collections.sort(nNameValueMap);			
		mFileSaved = false;
	}
}
